package master.common.data;

import org.json.simple.JSONArray;
import org.json.simple.JSONAware;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 将一个 List 转成适合于 Ext Tree 的 JSON 结构
 *
 * 通过 ID, PARENT_ID 匹配
 *
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
 */
public class TreeJSON {

    // 映射到类中的Field
    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String URL = "url";
    public static final String ICON = "icon";
    public static final String PARENT_ID = "parentId";

    public static interface Callback {
        public void updateJSON(final JSONObject json);
    }

    public static JSONArray fromListOfObject(List<? extends JSONAware> datas) {
        return fromListOfObject(datas, null);
    }
    /**
     * 从 List 中 构建 ext tree 的 json 数据
     * @param datas
     */
    public static JSONArray fromListOfObject(List<? extends JSONAware> datas, Callback callback) {
        List<JSONObject> jsonObjectList = new ArrayList<JSONObject>(datas.size());
        for(JSONAware obj : datas){
            // 转成JSONObject
            JSONObject jsonObject = (JSONObject)JSONValue.parse(JSONValue.toJSONString(obj));
            jsonObjectList.add(jsonObject);
        }
        return fromListOfJSONObject(jsonObjectList, callback);
    }

    /**
     * 从 List 中 构建 ext tree 的 json 数据
     * @param datas
     */
    public static JSONArray fromListOfJSONObject(List<? extends JSONObject> datas){
        // JSONObject 实现了 Map
        return fromListOfJSONObject(datas, null);
    }

    public static JSONArray fromListOfJSONObject(List<? extends JSONObject> datas, Callback callback){
        // JSONObject 实现了 Map
        return fromListOfMap(datas, callback);
    }

    /**
     * 从 List 中 构建 ext tree 的 json 数据
     * @param datas
     */
    public static JSONArray fromListOfMap(final List<? extends Map> datas) {
        return fromListOfMap(datas, null);
    }

    public static JSONArray fromListOfMap(final List<? extends Map> datas, Callback callback) {
        final JSONArray jsonArray = new JSONArray();
        for(Map map : getRoot(datas)) {
            buildTreeNodeFromMap(map, jsonArray, datas, callback);
        }
        return jsonArray;
    }

    private static List<? extends Map> getRoot(final List<? extends Map> datas){
        List<Map> roots = new ArrayList<Map>();
        Iterator<? extends Map> it = datas.iterator();
        while(it.hasNext()){
            Map map = it.next();
            if("0".equals(map.get(PARENT_ID).toString())) { // PARENT_ID=0 为根节点
                roots.add(map);
                it.remove();
            }
        }
        return roots;
    }

    private static List<? extends Map> getChildren(final Map current, final List<? extends Map> datas){
        String id = current.get(ID).toString();
        List<Map> children = new ArrayList<Map>();
        Iterator<? extends Map> it = datas.iterator();
        while (it.hasNext()){
            Map map = it.next();
            if(map.get(PARENT_ID).toString().equals(id)) {
                children.add(map);
                it.remove();
            }
        }
        return children;
    }

    private static void buildTreeNodeFromMap(final Map map, final JSONArray parentJSONArray, final List<? extends Map> datas, final Callback callback){

        JSONObject json = new JSONObject();
        parentJSONArray.add(json);
        json.putAll(map);
        json.put("id", map.get(ID).toString());
        json.put("parentId", map.get(PARENT_ID).toString());
        json.put("text", map.get(NAME));
        json.put("url", map.get(URL));
        json.put("expanded", true);
//        json.put("singleClickExpand", true);
//        json.put("cls","cls");
        //TODO: 放到 callback 中
        if(map.get(ICON) == null){
            json.put("icon", "./images/class.gif");
        }
        else {
            json.put("icon", map.get(ICON));
        }

        JSONArray childJSONArray = new JSONArray();
        List<? extends Map> children = getChildren(map, datas);

        if(!children.isEmpty()) {
//            json.put("isClass",false);
            json.put("leaf", false);
            json.put("children", childJSONArray);
            for (Map child : children) {
                buildTreeNodeFromMap(child, childJSONArray, datas, callback);
            }
        }
        else {
//            json.put("isClass",true);
            json.put("leaf", true);
        }

        // execute callback
        if(callback != null) {
            callback.updateJSON(json);
        }

    }

}
